package shipNuking;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

public class Run {

	public static void main(String[] args) {

		System.out.print("\n");
		System.out.println("+++++++++++++++++++++++++++++++++++++++++++");
		System.out.println("++ shipNuking by Yves Grau, Tobias Bagg  ++");
		System.out.println("+++++++++++++++++++++++++++++++++++++++++++");
		System.out.print("\n");
		System.out.println("+++++++++++++++++++++++++++++++++++++");
		System.out.println("++ Info zum Spiel:                 ++");
		System.out.println("++ X => Feld ist mit Schiff belegt ++");
		System.out.println("++ - => Treffer auf Schiff         ++");
		System.out.println("++ 1 => Schuss ohne Treffer        ++");
		System.out.println("++ 2 => Schuss mit Treffer         ++");
		System.out.println("+++++++++++++++++++++++++++++++++++++");
		System.out.print("\n");

		String userInput = "";
		BufferedReader buffer = new BufferedReader(new InputStreamReader(
				System.in));

		System.out.println("Geben sie den gewuenschten Runmodus "
				+ "des Programms ein (Client/Server): ");

		try {
			userInput = buffer.readLine();
		} catch (IOException e) {
			e.printStackTrace();
		}

		if (userInput.equals("Client")) {
			// Client
			Client client = null;
			BufferedReader bufferClient = new BufferedReader(
					new InputStreamReader(System.in));

			System.out.println("Geben sie die IP Adresse des Servers an: ");

			try {
				String userCord = "";
				String serverAnswer = "false";
				String serverIp = bufferClient.readLine();
				String[] splittedInput;

				client = new Client(serverIp);

				Scanner in = new Scanner(client.getSock().getInputStream());
				PrintWriter out = new PrintWriter(client.getSock()
						.getOutputStream(), true);

				System.out.println("Verbindung hergestellt!");
				String actShip = "Schlachtschiff";
				int actLength = 5;

				// get positions of ships
				for (int i = 0; i < 5; i++) {
					serverAnswer = "false";
					switch (i) {
					case 1:
						actShip = "Fregatte";
						actLength = 3;
						break;
					case 3:
						actShip = "Kreuzer";
						actLength = 4;
						break;
					case 4:
						actShip = "Minensucher";
						actLength = 2;
						break;
					}

					System.out.println("Geben sie die Koordinaten des/der "
							+ actShip + " an (\"x1:y1:x2:y2\"); Laenge = "
							+ actLength);

					while (serverAnswer.equals("false")) {
						userCord = bufferClient.readLine();
						out.println(userCord);
						serverAnswer = in.nextLine();
						if (serverAnswer.equals("false")) {

							System.out
									.println("Die Koordinaten sind nicht korrekt. Nochmals eingeben: ");

						}
					}

					splittedInput = userCord.split(":");
					int[] splittedInputToInt = new int[4];

					for (int j = 0; j < 4; j++) {
						splittedInputToInt[j] = Integer
								.parseInt(splittedInput[j]);
					}

					switch (i) {
					case 0:
						client.setShip(splittedInputToInt[0],
								splittedInputToInt[1], splittedInputToInt[2],
								splittedInputToInt[3], new BattleShip());
						break;
					case 1:
						client.setShip(splittedInputToInt[0],
								splittedInputToInt[1], splittedInputToInt[2],
								splittedInputToInt[3], new Frigate());
						break;
					case 2:
						client.setShip(splittedInputToInt[0],
								splittedInputToInt[1], splittedInputToInt[2],
								splittedInputToInt[3], new Frigate());
						break;
					case 3:
						client.setShip(splittedInputToInt[0],
								splittedInputToInt[1], splittedInputToInt[2],
								splittedInputToInt[3], new Cruiser());
						break;
					case 4:
						client.setShip(splittedInputToInt[0],
								splittedInputToInt[1], splittedInputToInt[2],
								splittedInputToInt[3], new MineSearcher());
						break;
					}
					System.out.println("Bisher gesetzte Schiffe:");
					for (int k = 0; k < 10; k++) {
						for (int j = 0; j < 10; j++) {
							if (!(client.getShip(j, k))) {
								System.out.print("X");
							}else{
								System.out.print("0");
							}
							
							if (j == 9) {
								System.out.print("\n");
							}

						}
					}
				}

				client.getSock().close();
				client.setSock(serverIp);
				in = new Scanner(client.getSock().getInputStream());
				out = new PrintWriter(client.getSock().getOutputStream(), true);

				// start Game
				String answer = "";
				boolean endGame = false;

				while (!answer.equals("endLose") && !endGame) {

					int cordX = 10;
					int cordY = 10;
					boolean isInt = false, reShoot = true, firstRound2 = true;

					while (reShoot) {

						System.out.println("Schussfeld:");
						for (int i = 0; i < 10; i++) {
							for (int j = 0; j < 10; j++) {
								System.out.print(client.getField(j, i));
								if (j == 9) {
									System.out.print("\n");
								}

							}
						}

						System.out.println("Dein Spielfeld:");
						for (int i = 0; i < 10; i++) {
							for (int j = 0; j < 10; j++) {
								if (!(client.getShip(j, i))
										&& client.getFieldServer(j, i) == 1) {
									System.out.print("-");
								} else if (!(client.getShip(j, i))
										&& client.getFieldServer(j, i) == 0) {
									System.out.print("X");
								} else if (client.getShip(j, i)
										&& client.getFieldServer(j, i) == 1) {
									System.out.print("1");
								} else {
									System.out.print("O");
								}
								if (j == 9) {
									System.out.print("\n");
								}

							}
						}

						System.out
								.println("Warte auf anderen Spieler bzw. Server ...");

						isInt = false;
						if (firstRound2) {
							answer = in.nextLine();
							firstRound2 = false;
						}
						// get fields at which the server player shooted
						if (answer.equals("transmitting")) {
							int bufferCordX = 0;
							int bufferCordY = 0;
							boolean firstRound = true;

							while (!answer.equals("transEnd")) {
								if (firstRound) {
									answer = in.nextLine();
									firstRound = false;
								}
								bufferCordX = Integer.parseInt(answer);
								answer = in.nextLine();
								bufferCordY = Integer.parseInt(answer);
								answer = in.nextLine();
								client.setFieldServer(bufferCordX, bufferCordY,
										1);
							}
						}

						System.out.println("Wohin moechten sie schiessen?");

						while (!isInt) {
							try {
								System.out.print("x = ");
								cordX = Integer.parseInt(buffer.readLine());

								System.out.print("y = ");
								cordY = Integer.parseInt(buffer.readLine());
								isInt = true;
							} catch (NumberFormatException e) {
								System.out
										.println("Sie muessen eine Zahl eingeben!");
							}
						}

						// send input to server and get it checked on validity
						out.println(cordX);
						out.println(cordY);

						answer = in.nextLine();
						if (answer.equals("endLose")) {
							System.out.println("Vorbei! Du verlierst leider!");
							reShoot = false;
						} else if (answer.equals("endWin")) {
							System.out.println("Vorbei! Du gewinnst!");
							reShoot = false;
							endGame = true;
						} else if (answer.equals("hit")) {
							System.out
									.println("Treffer! Sie duerfen nochmal schiessen.");
							client.setField(cordX, cordY, 2);
						} else if (answer.equals("sunk")) {
							System.out
									.println("Treffer und Zernichtet! Sie duerfen nochmal schiessen.");
							client.setField(cordX, cordY, 2);
						} else if (answer.equals("false")) {
							System.out
									.println("Kein gueltiger Schuss. Erneut Eingeben: ");
							reShoot = true;
						} else if (answer.equals("miss")) {
							System.out.println("Daneben!");
							client.setField(cordX, cordY, 1);
							reShoot = false;
						}

					}
				}

			} catch (UnknownHostException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				if (client.getSock() != null) {
					try {
						client.getSock().close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		} else if (userInput.equals("Server")) {
			// Server
			Socket client = null;

			try {

				Server server = new Server();

				ThreadServer t = new ThreadServer(server.getSocket(), server);
				t.start(); // Thread for Client which places ships into an array

				System.out
						.println("Wo soll das Schlachtschiff platziert werden? (\"x1:y1:x2:y2\"); Laenge = 5");
				server.shipPlacementRoutineServer(new BattleShip(),
						server.fieldShipsPlayerOne);
				System.out.println("Bisher gesetzte Schiffe:");
				for (int i = 0; i < 10; i++) {
					for (int j = 0; j < 10; j++) {
						if (server.fieldShipsPlayerOne[j][i] != null) {
							System.out.print("X");
						}else{
							System.out.print("0");
						}
						
						if (j == 9) {
							System.out.print("\n");
						}
						
					}
				}
				
				System.out
						.println("Wo soll die Fregatte platziert werden? (\"x1:y1:x2:y2\"); Laenge = 3");
				server.shipPlacementRoutineServer(new Frigate(),
						server.fieldShipsPlayerOne);
				System.out.println("Bisher gesetzte Schiffe:");
				for (int i = 0; i < 10; i++) {
					for (int j = 0; j < 10; j++) {
						if (server.fieldShipsPlayerOne[j][i] != null) {
							System.out.print("X");
						}else{
							System.out.print("0");
						}
						
						if (j == 9) {
							System.out.print("\n");
						}
						
					}
				}
				
				System.out
						.println("Wo soll die Fregatte platziert werden? (\"x1:y1:x2:y2\"); Laenge = 3");
				server.shipPlacementRoutineServer(new Frigate(),
						server.fieldShipsPlayerOne);
				System.out.println("Bisher gesetzte Schiffe:");
				for (int i = 0; i < 10; i++) {
					for (int j = 0; j < 10; j++) {
						if (server.fieldShipsPlayerOne[j][i] != null) {
							System.out.print("X");
						}else{
							System.out.print("0");
						}
						
						if (j == 9) {
							System.out.print("\n");
						}
						
					}
				}
				System.out.println("Bisher gesetzte Schiffe:");
				System.out
						.println("Wo soll der Kreuzer platziert werden? (\"x1:y1:x2:y2\"); Laenge = 4");
				server.shipPlacementRoutineServer(new Cruiser(),
						server.fieldShipsPlayerOne);
				System.out.println("Bisher gesetzte Schiffe:");
				for (int i = 0; i < 10; i++) {
					for (int j = 0; j < 10; j++) {
						if (server.fieldShipsPlayerOne[j][i] != null) {
							System.out.print("X");
						}else{
							System.out.print("0");
						}
						
						if (j == 9) {
							System.out.print("\n");
						}
						
					}
				}
				
				System.out
						.println("Wo soll der Minensucher platziert werden? (\"x1:y1:x2:y2\"); Laenge = 2");
				server.shipPlacementRoutineServer(new MineSearcher(),
						server.fieldShipsPlayerOne);

				System.out
						.println("Es wird auf die Platzierungen der Schiffe des"
								+ " anderen Spielers gewartet. Dies kann einen Moment dauern.");
				// end of placing Ships. yeah

				try {
					t.join(); // wait for the other thread
				} catch (InterruptedException e) {
					e.printStackTrace();
				}

				System.out.println("... Fertig!");
				// start Game

				int hitCordX = 0, hitCordY = 0;
				boolean isInt = false, shootAgain = true, endGame = false;

				client = server.getSocket().accept();
				Scanner in = new Scanner(client.getInputStream());
				PrintWriter out = new PrintWriter(client.getOutputStream(),
						true);

				System.out.println("Das Spiel hat begonnen!");

				while (!endGame) {
					shootAgain = true;

					System.out.println("Wohin moechten sie schiessen?");
					out.println("transmitting");
					while (shootAgain) {
						System.out.println("Schussfeld:");
						for (int i = 0; i < 10; i++) {
							for (int j = 0; j < 10; j++) {
								System.out
										.print(server.fieldHitsPlayerOne[j][i]);
								if (j == 9) {
									System.out.print("\n");
								}

							}
						}
						System.out.println("Dein Spielfeld:");
						for (int i = 0; i < 10; i++) {
							for (int j = 0; j < 10; j++) {
								if (server.fieldShipsPlayerOne[j][i] != null
										&& server.fieldHitsPlayerTwo[j][i] == 2) {
									System.out.print("-");
								} else if (server.fieldShipsPlayerOne[j][i] != null
										&& server.fieldHitsPlayerTwo[j][i] == 0) {
									System.out.print("X");
								} else if (server.fieldShipsPlayerOne[j][i] == null
										&& server.fieldHitsPlayerTwo[j][i] == 1) {
									System.out.print("1");
								} else {
									System.out.print("O");
								}
								if (j == 9) {
									System.out.print("\n");
								}

							}
						}
						isInt = false;
						while (!isInt) {
							try {
								System.out.print("x = ");
								hitCordX = Integer.parseInt(buffer.readLine());

								System.out.print("y = ");
								hitCordY = Integer.parseInt(buffer.readLine());
								isInt = true;
							} catch (NumberFormatException e) {
								System.out
										.println("Sie muessen eine Zahl eingeben!");
							}
						}

						if (server.isShootAble(hitCordX, hitCordY,
								server.fieldHitsPlayerOne)) {
							server.fieldHitsPlayerOne[hitCordX][hitCordY] = 1;
							if (server.fieldShipsPlayerTwo[hitCordX][hitCordY] != null) {
								// != null => there is a ship on that index
								out.println(hitCordX);
								out.println(hitCordY);
								server.fieldShipsPlayerTwo[hitCordX][hitCordY]
										.shoot();
								System.out.println("Treffer!");
								server.fieldHitsPlayerOne[hitCordX][hitCordY] = 2;
								if (server.fieldShipsPlayerTwo[hitCordX][hitCordY]
										.getHits() == server.fieldShipsPlayerTwo[hitCordX][hitCordY]
										.getLength()) {
									System.out.println("... Versenkt!");
									server.increaseDefeatedShips(2);
								}
								shootAgain = true;
								System.out
										.println("Sie duerfen noch einmal schiessen!");
							} else {
								out.println(hitCordX);
								out.println(hitCordY);
								System.out.println("Vorbei!");
								shootAgain = false;
								out.println("transEnd");
							}

						} else {
							System.out
									.println("Die Koordinaten erlauben keinen gueltigen Schuss. Geben sie andere Koordinaten ein.");
							shootAgain = true;
						}

						if (server.getDefeatedShips(2) == 5) {
							System.out.println("Sieg! Spiel ist vorbei!");
							out.println("transEnd");
							out.println("endLose");
							endGame = true;
							shootAgain = false;
						}
					}

					shootAgain = true;
					if (!endGame) {
						System.out.println("Warte auf anderen Spieler ...");
						while (shootAgain) {
							hitCordX = Integer.parseInt(in.nextLine());
							hitCordY = Integer.parseInt(in.nextLine());
							if (server.isShootAble(hitCordX, hitCordY,
									server.fieldHitsPlayerTwo)) {
								server.fieldHitsPlayerTwo[hitCordX][hitCordY] = 1;
								if (server.fieldShipsPlayerOne[hitCordX][hitCordY] != null) {
									server.fieldShipsPlayerOne[hitCordX][hitCordY]
											.shoot();
									server.fieldHitsPlayerTwo[hitCordX][hitCordY] = 2;
									shootAgain = true;
									if (server.fieldShipsPlayerOne[hitCordX][hitCordY]
											.getHits() == server.fieldShipsPlayerOne[hitCordX][hitCordY]
											.getLength()) {
										server.increaseDefeatedShips(1);
										if (server.getDefeatedShips(1) == 5) {
											out.println("endWin");
											shootAgain = false;
											endGame = true;
											System.out
													.println("Vorbei! Sie haben leider verloren!");
										} else {
											out.println("sunk");
										}
									} else {
										out.println("hit");
									}
								} else {
									out.println("miss");
									shootAgain = false;
								}
							} else {
								out.println("false");
								shootAgain = true;
							}
						}
					}
				}

			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				if (client != null) {
					try {
						client.close();
					} catch (IOException e) {
					}
				}
			}

		}
	}
}
